﻿//***********************************************************************************************************************
//
//文件名(File Name):     IminectPlayerInfo .cs
//
//功能描述(Description):    体感数据处理
//
//作者(Author):		郭佳
//
//日期(Create Date):	
//
//修改记录(Revision History):
//			R1：
//				修改作者:
//				修改日期:
//				修改理由:				
//
//***********************************************************************************************************************
using UnityEngine;
using System;
using System.Threading;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;
using System.Text;
using IMIForUnity;

namespace IMIForUnity
{

    public class ImiManager : MonoBehaviour, IManager
    {

        private static ImiManager instance = null;
        private static ImiManagerImp imiManagerImp = null;
        private static MainThreadDispatcher mainThreadDispatcher = null;

        public bool DepthTexture = false;
        public bool SkeletonData = false;
        public bool UserDepthTexture = false;
        public bool ColorTexture = false;

        public bool StartAutomatically = true;

        public bool AutoUpgrade = false;

        public bool ShowDepthDetail = false;

        public bool IsPerformance = false;

        public bool useRootPermission = false;


        public ImiResolution.Type imageResolution = ImiResolution.Type._640x480;
        public ImiResolution.Type depthResolution = ImiResolution.Type._640x480;

        public event EventHandler OnDeviceOpened;
        public event EventHandler OnDeviceClosed;
        public event EventHandler OnDeviceConnected;
        public event EventHandler OnDeviceDisconnected;

        public DepthDataProcessor depthDataProcessor;

        /// <summary>
        /// Callback when Control Player has changed 
        /// </summary>
        /// <param name="code"></param>
        public delegate void OnControlPlayerChanged(int oldControleId, int newControlId);

        public delegate void OnPlayerEntered(int playerId);

        public delegate void OnPlayerLost(int playerId);

        public delegate void DepthDataProcessor(ushort[] depthData);

        public delegate void ColorDataProcessor(byte[] colorData);

        public delegate void RawDataProcessor(byte[] colorData,ushort[] depthData);

        public ImiGestureManager gestureManager;

        private bool isPaused;

        public ImiSkeleton.Index[] joints;

        public static ImiManager GetInstance()
        {
            if (!Exists())
            {
                //return null;
                throw new Exception("Could not find the ImiManager object. Please ensure you have added the ImiManager Prefab to your scene.");
            }
            return instance;
        }

        private ImiManager() { }

        void Awake()
        {
            if (instance == null)
            {
                instance = this;
                imiManagerImp = ImiManagerImp.GetInstance();
                mainThreadDispatcher = MainThreadDispatcher.GetInstance();
                DontDestroyOnLoad(this.gameObject);

                gestureManager = ImiGestureManager.GetInstance();

                //Keep Screen On!
                Screen.sleepTimeout = SleepTimeout.NeverSleep;
                joints = new ImiSkeleton.Index[(int)ImiSkeleton.Index.COUNT];

                for (int i = 0; i < (int)ImiSkeleton.Index.COUNT; i++)
                    joints[i] = (ImiSkeleton.Index)i;

            }
        }
        void Start()
        {
            if (StartAutomatically)
            {
                OpenDevice();
            }
        }

        void OnDestroy()
        {
            CloseDevice();
            instance = null;
        }


        public void Update()
        {
            if (mainThreadDispatcher != null)
            {
                mainThreadDispatcher.update();
            }
            //if (IsDeviceOpened())
            //{
            if (imiManagerImp != null)
                {
                    imiManagerImp.Update();
                }

            //}

            //Check Device State constantly to support Hot swap
            //imiManagerImp.CheckDeviceState();
        }


        private bool shouldRestart = false;
        void OnApplicationFocus(bool hasFocus)
        {
#if UNITY_ANDROID && !UNITY_EDITOR
 
            isPaused = !hasFocus;
            if (!isPaused && shouldRestart)
            {
                OpenDevice();
            }
#endif
        }

        void OnApplicationPause(bool pauseStatus)
        {
#if UNITY_ANDROID && !UNITY_EDITOR
            isPaused = pauseStatus;
            if (isPaused)
            {
                if (IsDeviceOpened())
                {
                    shouldRestart = true;
                    CloseDevice();
                }
            }
#endif
        }

        /// <summary>
        /// If instance Exists
        /// </summary>
        /// <returns></returns>
        private static bool Exists()
        {
            return instance != null;
        }


        /// <summary>
        /// Check if the device is opened and ready to use
        /// </summary>
        /// <returns></returns>
        public bool IsDeviceOpened()
        {
            if (imiManagerImp != null)
                return imiManagerImp.IsDeviceOpened();
            else
                return false;
        }

        internal void _OnDeviceOpened()
        {
            if (IsDeviceOpened())
            {
                if (OnDeviceOpened != null)
                    OnDeviceOpened.Invoke(this, EventArgs.Empty);
            }
        }

        internal void _OnDeviceClosed()
        {
            if (!IsDeviceOpened())
            {
                if (OnDeviceClosed != null)
                    OnDeviceClosed.Invoke(this, EventArgs.Empty);
            }
        }

        internal void _OnDeviceConnected()
        {
            if (OnDeviceConnected != null)
                OnDeviceConnected.Invoke(this, EventArgs.Empty);

        }

        internal void _OnDeviceDisconnected()
        {
            if (OnDeviceDisconnected != null)
                OnDeviceDisconnected.Invoke(this, EventArgs.Empty);

        }

        /// <summary>
        /// Open Device and Open Default Streams
        /// </summary>
        public void OpenDevice()
        {
            if (IsDeviceOpened())
            {
                Debug.Log("Device Has Already Opened! Don't Open Again!");
                _OnDeviceOpened();
                return;
            }
            imiManagerImp.Open();
        }


        /// <summary>
        /// Open Device and specific streams
        /// </summary>
        /// <param name="openDepthTexture"></param>
        /// <param name="openSkeletonData"></param>
        /// <param name="openUserDepthTexture"></param>
        /// <param name="openColorTexture"></param>
        public void OpenDevice(bool openDepthTexture, bool openSkeletonData, bool openUserDepthTexture, bool openColorTexture)
        {
            this.DepthTexture = openDepthTexture;
            this.SkeletonData = openSkeletonData;
            this.UserDepthTexture = openUserDepthTexture;
            this.ColorTexture = openColorTexture;
            OpenDevice();
        }

        public ImiDevice GetDevice()
        {
            return null;
        }


        /// <summary>
        /// 关闭设备
        /// </summary>
        public void CloseDevice()
        {
            if (!IsDeviceOpened())
            {
                Debug.Log("Device Has Already Closed! Don't Close Again!");
                _OnDeviceClosed();
                return;
            }
            imiManagerImp.Close();
            if (OnDeviceClosed != null)
            {
                OnDeviceClosed.Invoke(this, EventArgs.Empty);
            }
        }


        public ImiResolution GetColorResolution()
        {
            return imiManagerImp.GetColorResolution();
        }

        public ImiResolution GetDepthResolution()
        {
            return imiManagerImp.GetDepthResolution();
        }

        /// <summary>
        /// 获取颜色图像.
        /// </summary>
        /// <returns></returns>
        public Texture2D GetColorTexture()
        {
            return imiManagerImp.GetColorTexture();
        }

        public Texture2D GetMainUserColorTexture()
        {
            return imiManagerImp.GetMainUserColorTexture();
        }

        public Texture2D GetSubUserColorTexture()
        {
            return imiManagerImp.GetSubUserColorTexture();
        }

        public Texture2D GetDepthTexture()
        {
            return imiManagerImp.GetDepthTexture();
        }

        /// <summary>
        /// 获取包含玩家的深度图像.
        /// </summary>
        /// <returns></returns>
        public Texture2D GetUserDepthTexture()
        {
            return imiManagerImp.GetUserDepthTexture();
        }

        /// <summary>
        /// 获得主要玩家深度图信息
        /// </summary>
        /// <returns>主要玩家深度图</returns>
        public Texture2D GetMainUserDepthTexture()
        {
            return imiManagerImp.GetMainUserDepthTexture();
        }

        //public void AddGestures(IminectGestures.Gestures gesture)
        //{
        //    imiManagerImp.AddGesture(gesture);
        //}

        /// <summary>
        /// 获得第二个玩家的深度图信息
        /// </summary>
        /// <returns>第二个玩家深度图</returns>
        public Texture2D GetSubUserDepthTexture()
        {
            return imiManagerImp.GetSubUserDepthTexture();
        }

        /// <summary>
        /// 获取用户信息. 用户信息包含了骨骼信息.
        /// </summary>
        /// <returns></returns>
        public Dictionary<int, ImiPlayerInfo> GetPlayerInfos()
        {
            return imiManagerImp.playerInfos;
        }

        /// <summary>
        /// 根据Id获取用户信息
        /// </summary>
        /// <param name="userIndex">用户Id</param>
        /// <returns></returns>
        public ImiPlayerInfo GetPlayerInfo(int userIndex)
        {
            return imiManagerImp.GetPlayerInfo(userIndex);
        }

        /// <summary>
        /// 设置控制玩家ID.
        /// </summary>
        /// <param name="index"></param>
        public void SetControlPlayerId(int userId)
        {
            imiManagerImp.SetControlPlayerId(userId);
        }

        /// <summary>
        /// 设置跟踪玩家的模式（最近或者挥手）
        /// </summary>
        /// <param name="mode"></param>
        public void SetUserTrackingMode(UserTrackingMode mode)
        {

        }

        /// <summary>
        /// 设置跟踪的UserId
        /// </summary>
        /// <param name="userId">玩家的id</param>
        /// <returns>跟踪成功或者失败</returns>
        public ErrorCode SetTrackingUserId(int userId)
        {
            return ErrorCode.OK;
        }

        public int GetControlPlayerId()
        {
            return imiManagerImp.GetControlPlayerId();
        }

        public int GetSubPlayerId()
        {
            return imiManagerImp.GetSubPlayerId();
        }

        public void SetDepthDataProcessor(DepthDataProcessor processor)
        {
            imiManagerImp.SetDepthDataProcessor(processor);
        }

        public void SetColorDataProcessor(ColorDataProcessor processor)
        {
             imiManagerImp.SetColorDataProcessor(processor);
        }

        public void SetRawDataProcessor(RawDataProcessor processor)
        {
             imiManagerImp.SetRawDataProcessor(processor);
        }

        public void SetControlPlayerChangeListener(OnControlPlayerChanged observer)
        {
            imiManagerImp.SetControlPlayerChangeListener(observer);
        }

        public Texture2D GetColorTexture(int userId)
        {
            return null;
        }

        public Texture2D GetColorTexture(List<int> ids)
        {
            return null;
        }

        public Texture2D GetUserDepthTexture(int userId)
        {
            return null;
        }

        public Texture2D GetUserColorTextureInCenter(int userId)
        {
            return null;
        }



        public Texture2D GetUserDepthTexture(List<int> userId)
        {
            return null;
        }

        public void SetPlayerEnteredListener(OnPlayerEntered observer)
        {
        }

        public void SetPlayerLostListener(OnPlayerLost observer)
        {
        }
    }
}
